﻿using System;
using System.Collections.Generic;
using System.IO;

namespace Aeon.Emulator.Interrupts
{
    /// <summary>
    /// Emulates the 2F multiplex interrupt.
    /// </summary>
    internal sealed class MultiplexInterruptHandler : IInterruptHandler
    {
        #region Constructors
        /// <summary>
        /// Initializes a new instance of the MultiplexInterruptHandler class.
        /// </summary>
        public MultiplexInterruptHandler()
        {
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Gets the interrupts which are handled by this handler.
        /// </summary>
        IEnumerable<InterruptHandlerInfo> IInterruptHandler.HandledInterrupts
        {
            get { return new InterruptHandlerInfo[] { 0x2F }; }
        }
        /// <summary>
        /// Gets the collection of multiplex interrupt handlers.
        /// </summary>
        public IList<IMultiplexInterruptHandler> Handlers
        {
            get { return this.handlers; }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Called when the interrupt handler should perform its action.
        /// </summary>
        /// <param name="interrupt">Raised interrupt number.</param>
        void IInterruptHandler.HandleInterrupt(int interrupt)
        {
            int id = this.processor.AH;

            foreach(var handler in this.handlers)
            {
                if(handler.Identifier == id)
                {
                    handler.HandleInterrupt();
                    return;
                }
            }

            System.Diagnostics.Debug.WriteLine(string.Format("Multiplex interrupt ID {0:X2}h not implemented.", id));
        }
        /// <summary>
        /// Invoked when the emulator enters a paused state.
        /// </summary>
        void IVirtualDevice.Pause()
        {
        }
        /// <summary>
        /// Invoked when the emulator resumes from a paused state.
        /// </summary>
        void IVirtualDevice.Resume()
        {
        }
        /// <summary>
        /// Invoked when the virtual device has been added to a VirtualMachine.
        /// </summary>
        /// <param name="vm">VirtualMachine which owns the device.</param>
        void IVirtualDevice.DeviceRegistered(VirtualMachine vm)
        {
            this.processor = vm.Processor;
        }
        /// <summary>
        /// Invoked when the device should save its current state to a <see cref="System.IO.Stream"/>.
        /// </summary>
        /// <param name="destination"><see cref="System.IO.Stream"/> to which the state is saved.</param>
        void IVirtualDevice.SaveCurrentState(Stream destination)
        {
        }
        /// <summary>
        /// Invoked when the device should restore its state from a <see cref="System.IO.Stream"/>.
        /// </summary>
        /// <param name="source"><see cref="System.IO.Stream"/> from which the state is restored.</param>
        void IVirtualDevice.RestoreState(Stream source)
        {
        }
        /// <summary>
        /// Releases resources used by the device.
        /// </summary>
        void IDisposable.Dispose()
        {
        }
        #endregion

        #region Private Fields
        /// <summary>
        /// Current processor instance.
        /// </summary>
        private Processor processor;
        /// <summary>
        /// List of multiplex interrupt handlers.
        /// </summary>
        private readonly List<IMultiplexInterruptHandler> handlers = new List<IMultiplexInterruptHandler>();
        #endregion
    }
}
